﻿
using System;
using System.Linq;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Threading.Tasks;

using Kalman;
using Kalman.Extensions;
using Newtonsoft.Json.Linq;
using Kalman.Security;
using System.ComponentModel;

namespace QuDao
{
    /// <summary>
    /// 数据表sys_user关联的业务对象，处理该表相关的业务逻辑
    /// </summary>
    public sealed partial class SysUserBO : SingletonBase<SysUserBO>
    {
        readonly IFreeSql fsql;
        public SysUserBO() : base()
        {
            fsql = ServiceLocator.Instance.GetRequiredService<IFreeSql>();
        }

        #region Generate Code

        /// <summary>
        /// 获取用户
        /// </summary>
        /// <param name="id">主键ID的值</param>
        /// <returns></returns>
        public T GetItem<T>(long id)
        {
            if (id <= 0) return default;
            var item = fsql.Select<SysUser>().Where(a => a.UserID == id).ToOne<T>();
            return item;
        }

        public SysUser GetItem(long id)
        {
            return GetItem<SysUser>(id);
        }

        /// <summary>
        /// 获取用户数据列表
        /// </summary>
        /// <param name="pageIndex">页索引，从1开始</param>
        /// <param name="pageSize">每页记录数，默认10</param>
        /// <returns></returns>
        public List<T> GetList<T>(int pageIndex = 1, int pageSize = 10)
        {
            var list = fsql.Select<SysUser>().Page(pageIndex, pageSize).ToList<T>();
            return list;
        }

        /// <summary>
        /// 获取用户数据列表
        /// </summary>
        /// <returns></returns>
        public List<T> GetList<T>(long[] ids)
        {
            var list = fsql.Select<SysUser>().Where(a => ids.Contains(a.UserID)).ToList<T>();
            return list;
        }

        public int SetEnable(long id, bool isEnable)
        {
            return fsql.Update<SysUser>(id).Set(a => a.IsEnable, isEnable).ExecuteAffrows();
        }
        /// <summary>
        /// 删除用户数据
        /// </summary>
        /// <returns>返回影响行数</returns>
        public int Delete(long[] ids)
        {
            return fsql.Delete<SysUser>().Where(a => ids.Contains(a.UserID)).ExecuteAffrows();
        }

        /// <summary>
        /// 删除用户数据
        /// </summary>
        /// <returns>返回影响行数</returns>
        public int Delete(long id)
        {
            var ids = new long[] { id };
            return Delete(ids);
        }

        /// <summary>
        /// 后台查询数据（分页）
        /// </summary>
        /// <param name="req">分页查询请求对象</param>
        public PagingResult<T> Query<T>(PagingRequest req, int tid)
        {
            var select = fsql.Select<SysUser>().WhereIf(tid > 0, a => a.TID == tid);
            foreach (var item in req.FilterItems)
            {
                switch (item.Field)
                {
                    case "UserID":
                        select.Where(a => a.UserID == int.Parse(item.Value));
                        break;
                    case "UserType":
                        select.Where(a => a.UserType == int.Parse(item.Value));
                        break;
                    //case "UserName":
                    //    select.Where(a => a.UserName.Contains(item.Value));
                    //    break;
                    default:
                        break;
                }
            }

            if (!string.IsNullOrEmpty(req.SortExp))
            {
                select.OrderBy(req.SortExp);//自定义排序
            }
            else
            {
                select.OrderByDescending(a => a.UserID);//默认排序
            }

            var sql = select.ToSql();

            var list = select.Count(out var total).Page(req.PageIndex, req.PageSize).ToList<T>();
            return new PagingResult<T>
            {
                PageIndex = req.PageIndex,
                PageSize = req.PageSize,
                Data = list,
                Total = (int)total
            };
        }

        public PagingResult<SysUser> Query(PagingRequest req, int tid)
        {
            return Query<SysUser>(req, tid);
        }

        #endregion

        /// <summary>
        /// 根据用户名（登录账号）获取用户信息
        /// </summary>
        public T GetItemByUserName<T>(string userName)
        {
            return fsql.Select<SysUser>().Where(a => a.UserName == userName).ToOne<T>();
        }

        /// <summary>
        /// 判断用户名（登录账号）是否存在
        /// </summary>
        public bool IsExistUserName(string userName)
        {
            return fsql.Select<SysUser>().Any(a => a.UserName == userName);
        }

        /// <summary>
        /// 获取密码哈希值
        /// </summary>
        /// <param name="pwdMD5">密码明文MD5加密后的值</param>
        /// <param name="pwdSalt">用于对密码进行混淆加密</param>
        /// <returns></returns>
        public string GetPasswordHash(string pwdMD5, string pwdSalt)
        {
            var hash = HashCryto.GetHash2String($"{pwdMD5.ToUpper()}#{pwdSalt}", HashAlgorithmType.SHA256);
            return hash;
        }

        /// <summary>
        /// 登录校验
        /// </summary>
        /// <param name="userName">登录账号</param>
        /// <param name="pwdMD5">密码明文MD5加密</param>
        /// <returns></returns>
        public SysUser CheckLogin(string userName, string password)
        {
            var item = GetItemByUserName<SysUser>(userName);
            if (item == null || !item.IsEnable) throw new AppException($"登录账号不存在或已停用：{userName}");

            var pwdMD5 = HashCryto.GetHash2String(password, HashAlgorithmType.MD5);
            var pwdHash = GetPasswordHash(pwdMD5, item.PwdSalt);
            if (item.PwdHash != pwdHash) throw new AppException("登录密码不正确");

            fsql.Update<SysUser>(item.UserID)
                .Set(a => a.LoginCount + 1)
                .Set(a => a.LastLoginTime, DateTime.Now)
                .ExecuteAffrows();

            return item;
        }

        /// <summary>
        /// 新增用户
        /// </summary>
        public long Add(string pwd, SysUser entity)
        {
            if (string.IsNullOrEmpty(pwd)) pwd = "123456";
            if (IsExistUserName(entity.UserName)) throw new AppException($"用户账号已存在：{entity.UserName}");
            if (entity.UserType > 1 && entity.TID == 0) throw new AppException("租户不能为空");
            if (entity.UserType == 1) entity.TID = 0;

            //if (entity.UserType == 2)
            //{
            //    var area = AreaBO.Instance.GetArea(entity.CountyID);
            //    if(area == null || area.AreaLevel != 3) throw new AppException("运营账号关联区县数据无效");

            //    entity.CountyName = area.AreaName;
            //}

            var pwdSalt = GuidUtil.New32Upper();
            var pwdMD5 = HashCryto.GetHash2String(pwd, HashAlgorithmType.MD5);

            entity.PwdSalt = pwdSalt;
            entity.PwdHash = GetPasswordHash(pwdMD5, pwdSalt);
            entity.CreateTime = DateTime.Now;
            entity.ModifyTime = DateTime.Now;
            entity.IsEnable = true;
            entity.UserID = (int)fsql.Insert(entity).ExecuteIdentity();
            return entity.UserID;
        }

        /// <summary>
        /// 修改用户
        /// </summary>
        public int Modify(SysUserDto dto)
        {
            var item = GetItem<SysUser>(dto.UserID) ?? throw new AppException($"用户不存在：{dto.UserID}");
            var update = fsql.Update<SysUser>(dto.UserID).Set(a => a.ModifyTime, DateTime.Now);
            if (dto.UserName != item.UserName) update.Set(a => a.UserName, dto.UserName);
            if (dto.UserType != item.UserType) update.Set(a => a.UserType, dto.UserType);
            if (dto.RoleID != item.RoleID) update.Set(a => a.RoleID, dto.RoleID);
            if (dto.Mobile != item.Mobile) update.Set(a => a.Mobile, dto.Mobile);
            if (dto.TrueName != item.TrueName) update.Set(a => a.TrueName, dto.TrueName);
            if (dto.LoginCount != item.LoginCount) update.Set(a => a.LoginCount, dto.LoginCount);
            if (dto.LastLoginTime != item.LastLoginTime) update.Set(a => a.LastLoginTime, dto.LastLoginTime);
            //if (dto.ShopID != item.ShopID) update.Set(a => a.ShopID, dto.ShopID);
            if (dto.Memo != item.Memo) update.Set(a => a.Memo, dto.Memo);


            //if (dto.CountyID != item.CountyID)
            //{
            //    var area = AreaBO.Instance.GetArea(dto.CountyID);
            //    if (area == null || area.AreaLevel != 3) throw new AppException("运营账号关联区县数据无效");

            //    update.Set(a => a.CountyID, dto.CountyID).Set(a => a.CountyName, area.AreaName);
            //}

            return update.ExecuteAffrows();
        }

        /// <summary>
        /// 修改密码
        /// </summary>
        /// <param name="id"></param>
        /// <param name="newPwdMD5">新密码（MD5加密）</param>
        /// <param name="oldPwdMD5">老密码（MD5加密）</param>
        public void ModifyPwd(int id, string newPwdMD5, string oldPwdMD5)
        {
            var user = GetItem<SysUser>(id) ?? throw new AppException($"用户不存在：{id}");
            var pwdHash = GetPasswordHash(oldPwdMD5, user.PwdSalt);
            if (pwdHash != user.PwdHash) throw new AppException("旧密码不正确");

            pwdHash = GetPasswordHash(newPwdMD5, user.PwdSalt);
            fsql.Update<SysUser>(id).Set(a => a.PwdHash, pwdHash).ExecuteAffrows();
        }

        /// <summary>
        /// 重置密码
        /// </summary>
        /// <param name="id"></param>
        /// <param name="newPwd">新密码（MD5加密）</param>
        public void ResetPwd(int id, string newPwdMD5)
        {
            var user = GetItem<SysUser>(id) ?? throw new AppException($"用户不存在：{id}");
            var pwdHash = GetPasswordHash(newPwdMD5, user.PwdSalt);
            fsql.Update<SysUser>(id).Set(a => a.PwdHash, pwdHash).ExecuteAffrows();
        }

        /// <summary>
        /// 用户授权
        /// </summary>
        /// <param name="id">账号ID</param>
        /// <param name="roleID">角色ID</param>
        public void Authorize(int id, int roleID)
        {
            var item = GetItem<SysUser>(id) ?? throw new AppException($"用户不存在：{id}");
            if (item.RoleID == roleID) return;

            fsql.Update<SysUser>(id).Set(a => a.RoleID, roleID).ExecuteAffrows();
        }

    }
}
